// Go语言学习在线文档：https://books.studygolang.com/gobyexample/maps/
// ssk学习
package main

import (
	//"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"
)

var NameSlice []string

// import "math"
// import "time"

const constants string = "constant"

// 结构体
type Person struct {
	name string
	age  int
}

// type People
type Rect struct {
	width, height int
}

func init() {
	//fmt.Println("imp-init() come here.")
}

func Print() {
	fmt.Println("Hello!")
}

func addAction(x, y int) (z int) {
	//注意return的返回简写
	z = x + y
	return
}

func FormatStamp(stamp int64) string {
	return time.Unix(stamp, 0).Format("2006-01-02 15:04:05")
}

func main() {
	/*
		sum := addAction(3, 10) //这里是错误写法
		fmt.Println("sum:= ", sum)
	*/

	var a = 10
	fmt.Println("a:",a)

	time := FormatStamp(time.Now().Unix())
	fmt.Println("时间time:= ", time)
	
	//nowTime := time.Now()
	
	/*这是我的第一个简单的程序 */
	// fmt.Println("Hello,World!")
	// fmt.Println(constants)
	
	/*
			ticker := time.NewTicker(1 * time.Second)
		    i := 0
		    // 子协程
		    go func() {
		        for {
		            //<-ticker.C
		            i++
		            fmt.Println(<-ticker.C)
		            if i == 5 {
		                //停止
		                ticker.Stop()
		            }
		        }
		    }()
		    for {
		    }
	*/
	
	/*
		timer1 := time.NewTimer(2 * time.Second)
		//t1 := time.Now()
		//fmt.Printf("t1:%v\n", t1)
		t2 := <-timer1.C
		fmt.Printf("t2:%v\n", t2)
	*/
	
	//timer5 := time.NewTimer(3 * time.Second)
	//timer5.Reset(1 * time.Second)
	//fmt.Println(time.Now())
	//fmt.Println(<-timer5.C)
	
	/*
			var p *string
		    fmt.Println(p)
		    fmt.Printf("p的值是%s/n", p)
		    if p != nil {
		        fmt.Println("非空")
		    } else {
		        fmt.Println("空值")
		    }
	
			var a *int
			a = new(int)
		    *a = 100
		    fmt.Println(*a)
	*/
	
	/*
		Bob := Person{name: "Bob", age: 29}
		Tom := Person{"Tom", 28}
		var array [2]Person
		array[0] = Bob
		array[1] = Tom
		array[0].name = "BBBOb"
		tempItem := array[1]
		tempItem.name = "TTTom"
	*/
	mystr := strings.ReplaceAll("zxc.txt", ".txt", ".word")
	fmt.Println("刚开始ReplaceAll用法：", mystr, "长度为:", len(mystr))
	
	//sync.Map学习
	var myMapName sync.Map
	myMapName.Store("xiaoming", 6)
	myMapName.Store("anxing", 19)
	myMapName.Store("xiaohei", 7)
	fmt.Println("刚开始myMapName为：", myMapName)
	if value, isFind := myMapName.Load("xiaoming"); isFind {
		fmt.Println("sync.MapLoad加载的值是：", value)
	}
	
	var MyTestName string
	var MyValue uint64
	myMapName.Range(func(key, value interface{}) bool {
		MyTestName = fmt.Sprintf("%v", key)
		//NameSlice = append(NameSlice, MyTestName)
		MyValue, _ = strconv.ParseUint(fmt.Sprintf("%v", value), 10, 32)
		fmt.Println("key is", MyTestName, "value is", MyValue)
		return true
	})
	//fmt.Println("NameSlice is", NameSlice)
	/*
		sync.Map 的元素遍历，不能使用 GOLang 中for 循环 或者 for range 循环，
		要使用 Range 方法并配合一个回调函数进行遍历操作。
		通过回调函数返回遍历出来的键值对（即 key 和 value ）。
	*/
	
	/*
	
		//NameSlice = NameSlice[0:0]
	
	
		NameSlice = NameSlice[0:0]
		//myMapName.Range(StudentList)
		//fmt.Println("NameSlice is为:", NameSlice)
		fmt.Println("2.myMapName为：", myMapName)
	
		//myMapName.Delete("xiaoming")
		//myMapName.Delete("anxing")
	
		if value, isFind := myMapName.Load("xiaoming"); isFind {
			fmt.Println("是否找到值：", value)
		}
		//fmt.Println("NameSlice is为: ",myMapName.Load("xiaoming"))
		fmt.Println(myMapName.Load("anxing"))
		fmt.Println("myMapName字典为：", myMapName)
	*/
	
	/*
		//map学习
			easyMap := map[string]string{
				"xiaoming": "6",
				"anxing":   "19",
			}
			fmt.Println(easyMap)
	*/
	
	// fmt.Println(Bob,"\n","\n",Tom)
	// fmt.Println("1:= ",array[0].name,"2:= ",array[1].name)
	
	//疑问，这里为啥range没有起作用
	// for person := range array {
	// 	fmt.Printf("p:%+v\n", person)
	// 	// fmt.Println("p:%+v\n", person)
	// }
	//如果希望显示一些详情，可和 %+v 格式化符号配合。
	//这样可以直接打印出结构体的字段名和值。
	
	//这样写才对
	/*
				for _, person := range array {
					fmt.Printf("p:%+v\n", person)
				}
	
				//疑问❓没有用，
				articleJSON, _ := json.MarshalIndent(Bob, "", " ")
				fmt.Println(string(articleJSON))
				//这里应该把err带出来，更安全些；
	
				bobJSON, err := json.Marshal(Bob)
			    if err != nil {
			        fmt.Println(err.Error())
			    }
				// bobJSON[]byte类型，转化为string类型便于查看
		    	fmt.Println(string(bobJSON))
	
	*/
	
	/*
	   //变量
	   	var strOne string = "initial"
	   	fmt.Println(strOne)
	
	   	var b,c int = 1,2
	   	fmt.Println(b,c)
	
	   	var d = true
	   	fmt.Println(d)
	
	   	var e int
	   	fmt.Println(e)
	
	   	f := "short"
	   	fmt.Println(f)
	*/
	
	/*
	   //常量
	   const n = 50000000
	
	   const d = 3e20 / n
	
	   fmt.Println(d)
	
	   fmt.Println(math.Sin(n))
	
	   fmt.Println(int64(d))
	*/
	
	/*
	   //for循环
	   for i := 0; i < 5; i++ {
	   	fmt.Println(i)
	   	i += 1
	   }
	
	   for i := 0; i < 5; i++ {
	   	fmt.Println(i)
	   	i += 1
	   }
	
	   i :=  1
	   for i < 3{
	   	fmt.Println(i)
	   	i = i + 1
	   }
	*/
	
	/*
	   //if/else 分支结构
	   if 7%2 ==0 {
	   	fmt.Println("7 is even")
	   }else {
	   	fmt.Println("7 is odd")
	   }
	
	   if 8%2 ==0 {
	   	fmt.Println("8 is divisible by 4")
	   }
	
	   if num := 9; num < 0 {
	   	fmt.Println(num,"is negative")
	   }else if num < 10 {
	   	fmt.Println(num,"has 1 digit")
	   }else{
	   	fmt.Println(num,"has multiple digits")
	   }
	*/
	
	//分支结构-switch (方便的条件分支语句)
	/*
	   i := 2
	   fmt.Println("write",i,"as")
	   switch i {
	   case 1:
	   	fmt.Println("one")
	   case 2:
	   	fmt.Println("two")
	   case 3:
	   	fmt.Println("three")
	   }
	
	   var timeNowDay = time.Now().Weekday()
	   switch timeNowDay {
	   case time.Saturday,time.Sunday:
	   	fmt.Println("it's the weekend")
	   default:
	   	fmt.Println("it's a weekday")
	   }
	
	   t := time.Now()
	   switch {
	   case t.Hour() < 12:
	   	fmt.Println("it's before noon")
	   default:
	   	fmt.Println("it's after noon")
	   }
	*/
	
	//**数组
	/*
	   var a [5] int
	   fmt.Println("empty:",a)
	
	   a [4] = 100
	   fmt.Println("set:",a)
	   fmt.Println("get:",a[4])
	   fmt.Println("length:",len(a))
	
	   b := [5] int{1,2,3,4,5}
	   fmt.Println("dcl",b)
	
	*/
	
	//二维数组
	/*
	   var twoD [2][3] int
	   for i := 0; i < 2; i++ {
	   	for j := 0; j < 3; j++ {
	   		twoD[i][j] = i+j
	   	}
	   }
	   fmt.Println("2d: ",twoD)
	*/
	
	//slice 切片
	
	/*
		//letters := []string{"a", "b", "c", "d"}
			letters := make([]string, 0)
			letters = append(letters, "a")
			letters = append(letters, "b")
			letters = append(letters, "c")
			letters = append(letters, "d")
	
			letters = append(letters, "ssk")
			fmt.Println("letters:", letters)
	
			   s := make([]string, 3)
			   fmt.Println("empty:",s)
	
			   s[0] = "a"
			   s[1] = "b"
			   s[2] = "c"
			   fmt.Println("set:",s)
			   fmt.Println("get:",s[2])
			   fmt.Println("length:",len(s))
	
			   s = append(s,"d")
			   s = append(s,"e","f")
			   fmt.Println("append:",s)
			   //[a b c d e f]
	
			   c := make([]string,len(s))
			   copy(c,s)
			   fmt.Println("copyC:",c)
	
			   l := s[2:5]
			   fmt.Println("slice1:",l)
			   //[c d e]
	
			   l = s[:5]
			   fmt.Println("slice2:",l)
			   //[a b c d e f]
	
			   l = s[2:]
			   fmt.Println("slice3:",l)
			   //[c d e f]
	
			   t :=[]string{"g","h","i"}
			   fmt.Println("dcl:",t)
	
			   twoD := make([][]int, 3)
			   for i := 0; i < 3; i++ {
			   	innerLen := i+1
			   	twoD[i] = make([]int, innerLen)
	
			   	for j := 0; j < innerLen; j++ {
			   		twoD[i][j] = i + j
			   	}
			   }
			   fmt.Println("2d:",twoD)
	
	
			//数组的简写
				// s := make([...]string, 10){0,1,2,3,4,5,6,7,8,9} //错误写法
				s := [...]int{0,1,2,3,4,5,6,7,8,9}
				// fmt.Println("empty:",s.length) //错误的，没有这个写法
				length := len(s)
				// fmt.Println("length:",len(s))
				//fmt.Sprint(length)
				fmt.Println("length:", length)
	*/
	
	//map关联数组（字典）
	/*
		   m := make(map[string]int)
		   m["key1"] = 7
		   m["key2"] = 13
		   fmt.Println("map:",m)
		   //注意📢：一个map在使用fmt.Println打印的时候，是以map[k:v k:v]的格式输出的
		   //map: map[key1:7 key2:13]
	
		   value1 := m["key1"]
		   fmt.Println("get value key1:",value1)
		   fmt.Println("length:",len(m))
	
		   delete(m,"key2")
		   fmt.Println("deleted key2,then map is:",m)
	
		   _, prs := m["key2"]
		   fmt.Println("prs:",prs)
	
		   //通过这个语法在同一行申明和初始化一个新的map
		   n := map[string]int{"foo":1,"bar":2}
		   fmt.Println("map:",n)
	
		   //也可以这样简写
		// s := [...]int{0,1,2,3,4,5,6,7,8,9}
	*/
	
	//Range遍历
	/*
	   nums := []int{2,3,4}
	   {
	   sum :=0
	   for _, num := range nums {
	   	sum += num
	   }
	   fmt.Println("sum:", sum)
	   }
	
	   //range在数组和slice中都同样提供每个项的索引和值，上面
	   我们不需要索引，所以我们使用  空值定义符_来忽略它。有时候我们是需要这个索引值的
	   for i,num := range nums {
	   	if num == 3 {
	   		fmt.Println("index:",i)
	   	}
	   }
	
	   //range在map中迭代 “键”+“值”对
	   kvs := map[string]string{"a":"apple","b":"banana"}
	   for k,v := range kvs{
	   	fmt.Println(k,v)
	   }
	
	   //range 在字符串中迭代unicode编码。第一个返回值是rune的起始字节位置，然后第二个是rune自己。
	   for i, c := range "go" {
	   	fmt.Println(i, c)
	   }
	*/
	
	//函数
	/*
	   res := plusFunc(1,2)
	   fmt.Println("1+2=",res)
	   a,b := values(20,10)
	   fmt.Println("a:",a)
	   fmt.Println("b:",b)
	
	   summary := noParamsFunc()
	   fmt.Println("summary:",summary)
	*/
	
	// sum(1,2)
	/*
	   nums := []int{1,2,3,4,5}
	   sum(nums...)
	*/
	
	//闭包
	/*
	   nextInt := intSeq()
	   nextInt()
	   fmt.Println("nextInt:",nextInt())
	   // fmt.Println(nextInt())
	   newInt := intSeq()
	   fmt.Println("newInt:",newInt())
	*/
	
	//递归
	/*
	   fact := fact(7)
	   fmt.Println("fact:",fact)
	*/
	
	/*
	   //指针
	   i := 1
	   fmt.Println("initial:",i)
	
	   zeroVal(i)
	   fmt.Println("zeroVal:",i)
	
	   zeroPtr(&i)
	   fmt.Println("zeroPtr:",i)
	   fmt.Println("Pointer:",&i)
	*/
	
	//结构体
	/*
	   Bob :=Person{name:"Bob",age:29}
	   Tom :=Person{"Tom",28}
	   Alice :=Person{"Alice",27}
	   fmt.Println(Bob,"\n",Tom,"\n",Alice)
	   fmt.Println("Bob.name:",Bob.name)
	   }
	*/
	
	//结构体
	/*
		rect := Rect{width: 10, height: 5}
		fmt.Println("area: ", rect.area())
		perimeters := r.perim()
	*/
}

// 这里是sync.Map的遍历方法，依赖于一个函数
func StudentList(name, age interface{}) bool {
	nameStr := fmt.Sprintf("%v", name)
	NameSlice = append(NameSlice, nameStr)
	
	if len(NameSlice) == 0 {
		return false
	}
	return true
}

// 函数是go的中心
func noParamsFunc() int {
	return 1 + 2
}

func plusFunc(a int, b int) int {
	return a + b
}

func subtractionFunc(a int, b int) int {
	return a - b
}

// 两个返回值，多个返回值
func values(a int, b int) (int, int) {
	sum := a + b
	subtract := a - b
	return sum, subtract
}

// 变参函数
func sum(nums ...int) {
	fmt.Println(nums, " ")
	total := 0
	for _, num := range nums {
		total += num
	}
	fmt.Println("total:", total)
}

// 闭包
func intSeq() func() int {
	i := 0
	return func() int {
		i += 1
		return i
	}
}

// 递归
func fact(n int) int {
	if n == 0 {
		return 1
	}
	return n * fact(n-1)
}

// 指针
func zeroVal(ival int) {
	ival = 0
}

func zeroPtr(iptr *int) {
	*iptr = 0
}

func (r *Rect) area() int {
	return r.width * r.height
}

func (r Rect) perim() int {
	return 2*r.width + 2*r.height
}
